package com.lid.lib;


import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;

public class LabelViewHelper {

    private static final int LEFT_TOP = 1;
    private static final int RIGHT_TOP = 2;
    private static final int LEFT_BOTTOM = 3;
    private static final int RIGHT_BOTTOM = 4;

    private static final int DEFAULT_DISTANCE = 40;
    private static final int DEFAULT_HEIGHT = 20;
    private static final int DEFAULT_STROKE_WIDTH = 1;
    private static final int DEFAULT_TEXT_SIZE = 14;
    private static final int DEFAULT_BACKGROUND_COLOR = 0x9F27CDC0;
    private static final int DEFAULT_STROKE_COLOR = 0xFFFFFFFF;
    private static final int DEFAULT_TEXT_COLOR = 0xFFFFFFFF;
    private static final int DEFAULT_ORIENTATION = LEFT_TOP;
    private static final int DEFAULT_TEXT_STYLE = 0;

    private int distance;
    private int height;
    private int strokeWidth;
    private String text;
    private int backgroundColor;
    private int strokeColor;
    private int textSize;
    private int textStyle;
    private int textColor;
    private boolean visual;
    private int orientation;


    private Paint rectPaint;
    private Paint rectStrokePaint;

    private Path rectPath;
    private Path textPath;
    private Paint textPaint;
    private Rect textBound;

    private Context context;
    private int alpha;

    public LabelViewHelper(Context context, AttrSet attrs, String defStyleAttr) {

        this.context = context;


        height = AttrUtils.getDimensionFromAttr(attrs, "label_height", dip2Px(DEFAULT_HEIGHT));
        distance = AttrUtils.getDimensionFromAttr(attrs, "label_distance", dip2Px(DEFAULT_DISTANCE));
        strokeWidth = AttrUtils.getDimensionFromAttr(attrs, "label_strokeWidth", dip2Px(DEFAULT_STROKE_WIDTH));
        text = AttrUtils.getStringFromAttr(attrs, "label_text", "");
        backgroundColor = AttrUtils.getColorFromAttr(attrs, "label_backgroundColor", DEFAULT_BACKGROUND_COLOR);
        strokeColor = AttrUtils.getColorFromAttr(attrs, "label_strokeColor", DEFAULT_STROKE_COLOR);
        textSize = AttrUtils.getDimensionFromAttr(attrs, "label_textSize", dip2Px(DEFAULT_TEXT_SIZE));

        textColor = AttrUtils.getColorFromAttr(attrs, "label_textColor", DEFAULT_TEXT_COLOR);
        visual = AttrUtils.getBooleanFromAttr(attrs, "label_visual", true);
        String orientationtemp = AttrUtils.getStringFromAttr(attrs, "label_orientation", "LEFT_TOP");
        if ("LEFT_TOP".equals(orientationtemp)) {
            orientation = LEFT_TOP;
        } else if ("RIGHT_TOP".equals(orientationtemp)) {
            orientation = RIGHT_TOP;
        } else if ("LEFT_BOTTOM".equals(orientationtemp)) {
            orientation = LEFT_BOTTOM;
        } else if ("RIGHT_BOTTOM".equals(orientationtemp)) {
            orientation = RIGHT_BOTTOM;
        } else {
            orientation = LEFT_TOP;
        }

        rectPaint = new Paint();
        rectPaint.setDither(true);
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(Paint.Style.FILL_STYLE);

        rectStrokePaint = new Paint();
        rectStrokePaint.setDither(true);
        rectStrokePaint.setAntiAlias(true);
        rectStrokePaint.setStyle(Paint.Style.STROKE_STYLE);

        rectPath = new Path();
        rectPath.reset();

        textPath = new Path();
        textPath.reset();

        textPaint = new Paint();
        textPaint.setDither(true);
        textPaint.setAntiAlias(true);
        textPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        textPaint.setStrokeCap(Paint.StrokeCap.SQUARE_CAP);

    }

    public void onDraw(Canvas canvas, int measuredWidth, int measuredHeight) {
        if (!visual || text == null) {
            return;
        }

        float actualDistance = distance + height / 2;
        calcOffset(measuredWidth, measuredHeight);

        rectPaint.setColor(new Color(backgroundColor));
        if (alpha != 0) {
            rectPaint.setAlpha(alpha);
        }

        rectStrokePaint.setColor(new Color(strokeColor));
        rectStrokePaint.setStrokeWidth(strokeWidth);

        canvas.drawPath(rectPath, rectPaint);
        canvas.drawPath(rectPath, rectStrokePaint);

        textPaint.setTextSize(textSize);
        textPaint.setColor(new Color(textColor));

        textBound = textPaint.getTextBounds(text);
        textPaint.setFont(Font.DEFAULT_BOLD);

        float begin_w_offset = (1.4142135f * actualDistance) / 2 - textBound.getWidth() / 2;
        if (begin_w_offset < 0) begin_w_offset = 0;

        canvas.drawTextOnPath(textPaint, text, textPath, begin_w_offset, textBound.getHeight() / 2);
    }

    private void calcOffset(int measuredWidth, int measuredHeight) {
        float startPosX = measuredWidth - distance - height;
        float endPosX = measuredWidth;
        float startPosY = measuredHeight - distance - height;
        float endPosY = measuredHeight;

        float middle = height / 2;

        switch (orientation) {
            case 1: // LEFT_TOP

                rectPath.reset();
                rectPath.moveTo(0, distance);
                rectPath.lineTo(distance, 0);
                rectPath.lineTo(distance + height, 0);
                rectPath.lineTo(0, distance + height);
                rectPath.close();

                textPath.reset();
                textPath.moveTo(0, distance + middle);
                textPath.lineTo(distance + middle, 0);
                textPath.close();

                break;
            case 2: // RIGHT_TOP

                rectPath.reset();
                rectPath.moveTo(startPosX, 0);
                rectPath.lineTo(startPosX + height, 0);
                rectPath.lineTo(endPosX, distance);
                rectPath.lineTo(endPosX, distance + height);
                rectPath.close();

                textPath.reset();
                textPath.moveTo(startPosX + middle, 0);
                textPath.lineTo(endPosX, distance + middle);
                textPath.close();

                break;
            case 3: // LEFT_BOTTOM

                rectPath.reset();
                rectPath.moveTo(0, startPosY);
                rectPath.lineTo(distance + height, endPosY);
                rectPath.lineTo(distance, endPosY);
                rectPath.lineTo(0, startPosY + height);
                rectPath.close();

                textPath.reset();
                textPath.moveTo(0, startPosY + middle);
                textPath.lineTo(distance + middle, endPosY);
                textPath.close();

                break;
            case 4: // RIGHT_BOTTOM

                rectPath.reset();
                rectPath.moveTo(startPosX, endPosY);
                rectPath.lineTo(measuredWidth, startPosY);
                rectPath.lineTo(measuredWidth, startPosY + height);
                rectPath.lineTo(startPosX + height, endPosY);
                rectPath.close();

                textPath.reset();
                textPath.moveTo(startPosX + middle, endPosY);
                textPath.lineTo(endPosX, startPosY + middle);
                textPath.close();

                break;
        }
    }

    private int dip2Px(float dip) {
        DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes();
        return (int) (attributes.scalDensity * dip + 0.5f);
    }

    private int px2Dip(float px) {
        DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes();
        return (int) (px / attributes.scalDensity + 0.5f);
    }

    public void setLabelHeight(Component component, int height) {
        if (this.height != dip2Px(height)) {
            this.height = dip2Px(height);
            component.invalidate();
        }
    }

    public int getLabelHeight() {
        return px2Dip(this.height);
    }

    public void setLabelDistance(Component view, int distance) {
        if (this.distance != dip2Px(distance)) {
            this.distance = dip2Px(distance);
            view.invalidate();
        }
    }

    public int getLabelStrokeWidth() {
        return px2Dip(this.strokeWidth);
    }

    public void setLabelStrokeWidth(Component view, int strokeWidth) {
        if (this.strokeWidth != dip2Px(strokeWidth)) {
            this.strokeWidth = dip2Px(strokeWidth);
            view.invalidate();
        }
    }

    public int getLabelDistance() {
        return px2Dip(this.distance);
    }

    public boolean isLabelVisual() {
        return visual;
    }

    public void setLabelVisual(Component view, boolean visual) {
        if (this.visual != visual) {
            this.visual = visual;
            view.invalidate();
        }
    }

    public int getLabelOrientation() {
        return orientation;
    }

    public void setLabelOrientation(Component view, int orientation) {
        if (this.orientation != orientation && orientation <= 4 && orientation >= 1) {
            this.orientation = orientation;
            view.invalidate();
        }
    }

    public int getLabelTextColor() {
        return textColor;
    }

    public void setLabelTextColor(Component view, int textColor) {
        if (this.textColor != textColor) {
            this.textColor = textColor;
            view.invalidate();
        }
    }

    public int getLabelBackgroundColor() {
        return backgroundColor;
    }

    public void setLabelBackgroundColor(Component view, int backgroundColor) {
        if (this.backgroundColor != backgroundColor) {
            this.backgroundColor = backgroundColor;
            view.invalidate();
        }
    }

    public int getLabelStrokeColor() {
        return strokeColor;
    }

    public void setLabelStrokeColor(Component view, int strokeColor) {
        if (this.strokeColor != strokeColor) {
            this.strokeColor = strokeColor;
            view.invalidate();
        }
    }


    public void setLabelBackgroundAlpha(Component view, int alpha) {
        if (this.alpha != alpha) {
            this.alpha = alpha;
            view.invalidate();
        }
    }

    public String getLabelText() {
        return text;
    }

    public void setLabelText(Component view, String text) {
        if (this.text == null || !this.text.equals(text)) {
            this.text = text;
            view.invalidate();
        }
    }

    public int getLabelTextSize() {
        return px2Dip(this.textSize);
    }

    public void setLabelTextSize(Component view, int textSize) {
        if (this.textSize != textSize) {
            this.textSize = textSize;
            view.invalidate();
        }
    }


}